package nl.weeaboo.sh.view;

import java.awt.Dimension;
import java.awt.Rectangle;
import java.io.FileInputStream;
import java.io.IOException;

import javax.media.opengl.GL;

import nl.weeaboo.game.Game;
import nl.weeaboo.game.Log;
import nl.weeaboo.game.gl.GLDraw;
import nl.weeaboo.game.gl.GLImage;
import nl.weeaboo.game.gl.GLManager;
import nl.weeaboo.game.gl.GLTexture;
import timon.common.GraphicsUtil;

import com.sun.opengl.cg.CGcontext;
import com.sun.opengl.cg.CGparameter;
import com.sun.opengl.cg.CGprogram;
import com.sun.opengl.cg.CgGL;

public class CgManager {

	protected Game game;
	
	private CGcontext context;	
	//private int vertexProfile;
	private int fragmentProfile;

	private CGprogram fragmentProgram;
	
	public CgManager(Game game) {
		this.game = game;
	}
	
	//Functions
	public void dispose() {
		if (fragmentProgram != null) {
			CgGL.cgDestroyProgram(fragmentProgram);
			fragmentProgram = null;
		}
		if (context != null) {
			CgGL.cgDestroyContext(context);
			context = null;
		}
	}
	
	private void checkError() {
		int error = CgGL.cgGetError();
		if (error != 0) {
			Log.warning(CgGL.cgGetErrorString(error));				
		}		
	}
	
	public void init(GL gl) {
		if (context != null) {
			return;
		}
		
	    context = CgGL.cgCreateContext();

	    /*if (CgGL.cgGLIsProfileSupported(CgGL.CG_PROFILE_VP40)) {
	        vertexProfile = CgGL.CG_PROFILE_VP40;
		} else {
			Log.warning("Vertex Shaders not supported");
		}*/
	    if (CgGL.cgGLIsProfileSupported(CgGL.CG_PROFILE_FP40)) {
	        fragmentProfile = CgGL.CG_PROFILE_FP40;
		} else {
			Log.warning("Fragment Shaders not supported");
		}
	    
	    loadFragmentShader("test.cg");
	}
	
	void loadFragmentShader(String filename) {
		if (!CgGL.cgIsContext(context)) {
			return;
		}

	    try {	    	
			fragmentProgram = CgGL.cgCreateProgramFromStream(context, CgGL.CG_SOURCE,
					/*game.getInputStream(filename),*/
					new FileInputStream(filename),
					fragmentProfile, null, null);
			checkError();

			if (!CgGL.cgIsProgramCompiled(fragmentProgram)) {
				CgGL.cgCompileProgram(fragmentProgram);

				checkError();
			}

			CgGL.cgGLLoadProgram(fragmentProgram);
			checkError();
	    } catch (IOException e) {
			Log.error(e);
		}
	}
	
	int frame;
	public void test(GLManager glm, GLImage image, int w, int h) {
		frame++;
		
		GLTexture texture = image.getTexture();
		glm.setTexture(texture);
		if (texture.getTexturePtr() == 0) {
			glm.setTexture(null);
			return; //Not inited or being recreated this frame
		}

		CgGL.cgGLEnableProfile(fragmentProfile);
	    CgGL.cgGLBindProgram(fragmentProgram);
		checkError();

		double range = 5 + 5 * Math.sin(Math.PI * 2.0 * frame / 60.0);
		CGparameter rangeParam = CgGL.cgGetNamedParameter(fragmentProgram, "range");		
		CgGL.cgGLSetParameter1d(rangeParam, range);
		
		CGparameter textureParam = CgGL.cgGetNamedParameter(fragmentProgram, "texture");
		CgGL.cgGLSetTextureParameter(textureParam, texture.getTexturePtr());
		CgGL.cgGLEnableTextureParameter(textureParam);
		checkError();

		float uv[] = new float[4];
		//image.draw(glm, 0, 0, 100, 100);
		glm.getGL().glColor4f(1, 1, 1, 1);
		glm.getGL().glBindTexture(GL.GL_TEXTURE_2D, texture.getTexturePtr());
		GLDraw.getUV(uv, texture.getTexWidth(), texture.getTexHeight(), new Rectangle(0, 0, texture.getTexWidth(), texture.getTexHeight()));		
		Dimension d = GraphicsUtil.getProportionalScale(image.getWidth(), image.getHeight(), w, h);
		GLDraw.fillRect(glm.getGL(), 0, 0, d.width, d.height, uv);

		CgGL.cgGLDisableTextureParameter(textureParam);
	    CgGL.cgGLUnbindProgram(fragmentProfile);	    
		CgGL.cgGLDisableProfile(fragmentProfile);
	}
	
	//Getters
	
	//Setters
	
}
